7.2.9 利用重启策略进行容器的自我修复

通常建议在运行容器时配置好重启策略。这是容器的一种自我修复能力,可以在指定事件或者错误后重启来完成自我修复。

重启策略应用于每个容器,可以作为参数被强制传入 docker-container run 命令中,或者在Compose文件中声明(在使用Docker Compose以及Docker Stacks的情况下)。

截至本书撰写时,容器支持的重启策略包括 alwaysunless-stoppedon-failed

always 策略是一种简单的方式。除非容器被明确停止,比如通过 docker container stop 命令,否则该策略会一直尝试重启处于停止状态的容器。一种简单的证明方式是启动一个新的交互式容器,并在命令后面指定 --restart always 策略,同时在命令中指定运行Shell进程。当容器启动的时候,会登录到该Shell。退出Shell时会杀死容器中PID为1的进程,并且杀死这个容器。但是因为指定了 --restart always 策略,所以容器会自动重启。如果运行 docker container ls 命令,就会看到容器的启动时间小于创建时间。下面请看示例。

$ docker container run --name neversaydie -it --restart always alpine sh
//等待几秒后输入exit
/# exit
$ docker container ls
CONTAINER ID    IMAGE     COMMAND     CREATED           STATUS
0901afb84439    alpine    "sh"        35 seconds ago    Up 1 second

注意,容器于35s前被创建,但却在1s前才启动。这是因为在容器中输入退出命令的时候,容器被杀死,然后Docker又重新启动了该容器。

--restart always 策略有一个很有意思的特性,当daemon重启的时候,停止的容器也会被重启。例如,新创建一个容器并指定 --restart always 策略,然后通过 docker container stop 命令停止该容器。现在容器处于 Stopped (Exited) 状态。但是,如果重启Docker daemon,当daemon启动完成时,该容器也会重新启动。

alwaysunless-stopped 的最大区别,就是那些指定了 --restart unless-stopped 并处于 Stopped (Exited) 状态的容器,不会在Docker daemon重启的时候被重启。这个说法可能令人有点迷惑,接下来通过示例进行演示。

下面创建两个新容器,其中“always”容器指定 --restart always 策略,另一个“unless- stopped”容器指定了 --restart unless-stopped 策略。两个容器均通过 docker container stop 命令停止,接着重启Docker。结果“always”容器会重启,但是“unless-stopped”容器不会。

(1)创建两个新容器。

$ docker container run -d --name always \
  --restart always \
  alpine sleep 1d
$ docker container run -d --name unless-stopped \
  --restart unless-stopped \
  alpine sleep 1d
$ docker container ls
CONTAINER ID   IMAGE    COMMAND      STATUS        NAMES
3142bd91ecc4   alpine   "sleep 1d"   Up 2 secs     unless-stopped
4f1b431ac729   alpine   "sleep 1d"   Up 17 secs    always

现在有两个运行的容器了。一个叫作“always”,另一个叫作“unless-stopped”。

(2)停止两个容器。

$ docker container stop always unless-stopped
$ docker container ls -a
CONTAINER ID   IMAGE     STATUS                        NAMES
3142bd91ecc4   alpine    Exited (137) 3 seconds ago    unless-stopped
4f1b431ac729   alpine    Exited (137) 3 seconds ago    always

(3)重启Docker。

重启Docker的过程在不同的操作系统上可能不同。下面的示例中展示了如何在Linux上使用systemd重启Docker,在Windows Server 2016上可以使用restart-service重启。

$ systemlctl restart docker

(4)一旦Docker重启成功,检查两个容器的状态。

$ docker container ls -a
CONTAINER   CREATED           STATUS                        NAMES
314.cc4    2 minutes ago    Exited (137) 2 minutes ago     unless-stopped
4f1..729    2 minutes ago    Up 9 seconds                   always

注意到“always”容器(启动时指定了 --restart always 策略)已经重启了,但是“unless-stopped”容器(启动时指定了 --restart unless-stopped 策略)并没有重启。

on-failure 策略会在退出容器并且返回值不是0的时候,重启容器。就算容器处于 stopped 状态,在Docker daemon重启的时候,容器也会被重启。

如果读者使用Docker Compose或者Docker Stack,可以在service对象中配置重启策略,示例如下。

version: "3.5"
services:
  myservice:
    <Snip>
    restart_policy:
      condition: always | unless-stopped | on-failure

results matching ""

    No results matching ""